﻿/******************************************************************************
* SunnyUI.FrameDecoder 开源TCP、串口数据解码库。
* CopyRight (C) 2022-2023 ShenYongHua(沈永华).
* QQ群：56829229 QQ：17612584 EMail：SunnyUI@qq.com
*
* Blog:   https://www.cnblogs.com/yhuse
* Gitee:  https://gitee.com/yhuse/SunnyUI.FrameDecoder
*
* SunnyUI.FrameDecoder.dll can be used for free under the MIT license.
* If you use this code, please keep this note.
* 如果您使用此代码，请保留此说明。
******************************************************************************
* 文件名称: ByteBits.cs
* 文件说明: 8位无符号整数byte位索引类
* 当前版本: V1.0
* 创建日期: 2022-11-06
*
* 2022-11-06: V1.0.0 增加文件说明
******************************************************************************/

using System;
using System.Text;

namespace Sunny.FrameDecoder
{
    /// <summary>
    /// 表示byte的位集合
    /// 位索引(0 ~ 7)，为由低到高的位索引，最低位为0位
    /// </summary>
    public struct ByteBits : IComparable<ByteBits>
    {
        /// <summary>
        /// 字节值
        /// </summary>
        public byte Value;

        /// <summary>
        /// 位集合最大长度
        /// </summary>
        public int MaxLength => sizeof(byte) * 8;

        private int MaxUsePos => MaxLength - 1;

        /// <summary>
        /// byte的位集合
        /// </summary>
        /// <param name="value">字节</param>
        private ByteBits(byte value)
        {
            Value = value;
        }

        /// <summary>
        /// 从指定索引位置取高位
        /// </summary>
        /// <param name="index">索引 (0 ~ 7)，由低到高的位索引，最低位为0位</param>
        /// <param name="count">位的数量</param>
        /// <returns></returns>
        public ByteBits Take(int index, int count)
        {
            if (index < 0 || index > MaxUsePos)
            {
                throw new ArgumentOutOfRangeException("index", "index为 0 到 " + MaxUsePos + " 之间");
            }

            if (index - count < -1)
            {
                throw new ArgumentOutOfRangeException("count", "index之后取不到count位数值");
            }

            return new ByteBits(BitHelper.BitsByte(ToString().Substring(MaxUsePos - index, count)));
        }

        /// <summary>
        /// 获取或设置指定位的值
        /// </summary>
        /// <param name="index">索引 (0 ~ 7)，由低到高的位索引，最低位为0位</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <returns></returns>
        public bool this[int index]
        {
            get
            {
                if (index < 0 || index > MaxUsePos)
                {
                    throw new ArgumentOutOfRangeException("index", "index为 0 到 " + MaxUsePos + " 之间");
                }

                return ToString()[MaxUsePos - index] == '1';
            }
            set
            {
                if (index < 0 || index > MaxUsePos)
                {
                    throw new ArgumentOutOfRangeException("index", "index为 0 到 " + MaxUsePos + " 之间");
                }

                char[] v = ToString().AsSpan().ToArray();
                v[MaxUsePos - index] = value ? '1' : '0';
                Value = BitHelper.BitsByte(new string(v));
            }
        }

        /// <summary>
        /// 字符串显示各个位的值
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return BitHelper.BitsString(Value);
        }

        /// <summary>
        /// 字符串显示各个位的值，四位用空格分隔显示
        /// </summary>
        /// <returns></returns>
        public string DisplayText
        {
            get
            {
                var str = ToString();
                StringBuilder vs = new();
                for (int i = 0; i < MaxLength / 4; i++)
                {
                    vs.Append(str.Substring(i * 4, 4));
                    vs.Append(' ');
                }

                return vs.ToString();
            }

        }

        /// <summary>
        /// 从byte类型隐式转换
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static implicit operator ByteBits(byte value)
        {
            return new ByteBits(value);
        }

        /// <summary>
        /// 隐式转换为byte类型
        /// </summary>
        /// <param name="bits"></param>
        /// <returns></returns>
        public static implicit operator byte(ByteBits bits)
        {
            return bits.Value;
        }

        /// <summary>
        /// 获取哈希码
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }

        /// <summary>
        /// 比较是否和目标相等
        /// </summary>
        /// <param name="obj">目标</param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            return obj != null && obj is ByteBits && obj.GetHashCode() == GetHashCode();
        }

        /// <summary>
        /// 比较
        /// </summary>
        /// <param name="other">目标</param>
        /// <returns></returns>
        int IComparable<ByteBits>.CompareTo(ByteBits other)
        {
            if (this == other)
            {
                return 0;
            }

            if (Value > other.Value)
            {
                return 1;
            }

            return -1;
        }
    }
}